﻿//////////////////////////////////////////////////////////////////
//
// Form1.cs
//
// Copyright (c) 2012 Dan Pike.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Utilities;
using Wintellect.PowerCollections;

namespace ColorMap
{
   public partial class Main : Form
   {
      private static Logger logger_;

      public class PanelComparer : IComparer<Panel>
      {
         public int Compare(Panel a, Panel b)
         {
            int result = (int)a.Tag - (int)b.Tag;
            if (0 == result)
            {
               result = a.GetHashCode() - b.GetHashCode();
            }
            return result;
         }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      static Main()
      {
         logger_ = Program.Logger;
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      public Main()
      {
         InitializeComponent();
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void exitToolStripMenuItem_Click(object sender, EventArgs e)
      {
         Close();
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void Main_Load(object sender, EventArgs e)
      {
         SortedList<Panel, Panel> panels = new SortedList<Panel, Panel>(new PanelComparer());

         GetColorProperties(typeof(Color)).ForEach(colorInfo =>
            {
               string colorName = colorInfo.Name;
               Color color = (Color)colorInfo.GetGetMethod().Invoke(null, null);
               int colorIndex = Program.Settings.NamedColors.Value[colorName].Index.Value;
               Panel panel = CreatePanel(colorIndex, colorName, color);
               panels.Add(panel, panel);
            });

         // Sort the panels into index order
         panels.Values.ToList().ForEach(panel => colorLayout.Controls.Add(panel));
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void HandleMouseClick(object sender, MouseEventArgs e)
      {
         Panel panel = sender as Panel;
         if (null != panel)
         {
            if (e.Button == MouseButtons.Left)
            {
               if (SystemColors.Window == panel.BackColor)
               {
                  panel.BackColor = SystemColors.ActiveBorder;
               }
               else
               {
                  panel.BackColor = SystemColors.Window;
               }
            }
            else if (e.Button == MouseButtons.Right)
            {
               int index = colorLayout.Controls.IndexOf(panel);
               colorLayout.Controls.OfType<Panel>().ToList()
                  .ForEach(movePanel =>
                     {
                        if (SystemColors.Window == movePanel.BackColor)
                        {
                           movePanel.BackColor = SystemColors.ActiveBorder;
                           colorLayout.Controls.SetChildIndex(movePanel, index);
                        }
                     });
            }
         }
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="colorInfo"></param>
      private Panel CreatePanel(int index, string colorName, Color color)
      {
         Panel panel = new Panel();
         panel.Width = 100;
         panel.Height = 80;
         panel.BackColor = SystemColors.ActiveBorder;
         panel.Padding = new System.Windows.Forms.Padding(5);
         panel.BorderStyle = BorderStyle.FixedSingle;
         panel.Tag = index;
         panel.MouseClick += new MouseEventHandler(HandleMouseClick);

         Panel panelRGB = new Panel();
         panelRGB.Width = 100;
         panelRGB.Height = 20;
         panelRGB.Dock = DockStyle.Top;
         panelRGB.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panel.Controls.Add(panelRGB);

         Panel panelR = new Panel();
         panelR.Left = 0;
         panelR.Width = 30;
         panelR.Height = (20 * color.R) / 255;
         panelR.BackColor = Color.Red;
         panelR.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panelRGB.Controls.Add(panelR);

         Panel panelG = new Panel();
         panelG.Left = 30;
         panelG.Width = 30;
         panelG.Height = (20 * color.G) / 255;
         panelG.BackColor = Color.Green;
         panelG.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panelRGB.Controls.Add(panelG);

         Panel panelB = new Panel();
         panelB.Left = 60;
         panelB.Width = 30;
         panelB.Height = (20 * color.B) / 255;
         panelB.BackColor = Color.Blue;
         panelB.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panelRGB.Controls.Add(panelB);

         Label label = new Label();
         label.Width = 100;
         label.Height = 15;
         label.Text = colorName;
         label.Dock = DockStyle.Top;
         label.TextAlign = ContentAlignment.MiddleCenter;
         label.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panel.Controls.Add(label);

         Panel panelColor = new Panel();
         panelColor.BackColor = color;
         panelColor.Dock = DockStyle.Fill;
         panelColor.MouseClick += new MouseEventHandler((s, e) => HandleMouseClick(panel, e));
         panel.Controls.Add(panelColor);

         return panel;
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="colorType"></param>
      /// <returns></returns>
      private List<PropertyInfo> GetColorProperties(Type colorType)
      {
         return colorType.FindMembers(
            MemberTypes.Property, BindingFlags.Static | BindingFlags.Public,
            (info, notUsed) => (typeof(Color) == ((PropertyInfo)info).PropertyType), null)
            .Cast<PropertyInfo>().ToList();
      }

      ////////////////////////////////////////////////////////////////////////
      /// <summary>
      /// 
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void Main_FormClosed(object sender, FormClosedEventArgs e)
      {
         int index = 0;
         colorLayout.Controls.Cast<Panel>().ToList().ForEach(panel =>
            {
               string title = panel.Controls.OfType<Label>().First(label => 0 < label.Text.Length).Text;
               Program.Settings.NamedColors.Value[title].Index.Value = index++;
            });
      }
   }
}
